#include "include/jni.h"
#include "Lock.h"

JavaVM *jvm;

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_cabinet_lock_lib_LockControl_connect(JNIEnv *env, jobject thiz, jstring ip,
                                                      jint port, jint cabinetId) {
    Lock *lock = new Lock();
    jobject obj;
    obj = env->NewGlobalRef(thiz);
    lock->thiz = obj;
    lock->jvm = jvm;
    const char *_ip = env->GetStringUTFChars(ip, 0);
    if (lock->connect(_ip, port, cabinetId & 0xFF) != LOCK_OK) {
        delete lock;
        return LOCK_FAIL;
    }

    jlong handle = (jlong) lock;
    jclass clazz = env->GetObjectClass(obj);
    jfieldID handle_fieldID = env->GetFieldID(clazz, "handle", "J");
    env->SetLongField(obj, handle_fieldID, handle);

    jfieldID ip_fieldID = env->GetFieldID(clazz, "ip", "Ljava/lang/String;");
    env->SetObjectField(obj, ip_fieldID, ip);

    return LOCK_OK;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_cabinet_lock_lib_LockControl_disconnect(JNIEnv *env, jobject thiz) {
    jclass clazz = env->GetObjectClass(thiz);
    jfieldID handle_fieldID = env->GetFieldID(clazz, "handle", "J");
    jlong handle = env->GetLongField(thiz, handle_fieldID);
    if (handle == 0) {
        return LOCK_FAIL;
    }
    Lock *lock = (Lock *) handle;
    lock->disconnect();
    env->DeleteGlobalRef(lock->thiz);
    env->SetLongField(thiz, handle_fieldID, (jlong) 0);
    delete lock;
    return LOCK_OK;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_cabinet_lock_lib_LockControl_open(JNIEnv *env, jobject thiz, jint port) {
    jclass clazz = env->GetObjectClass(thiz);
    jfieldID handle_fieldID = env->GetFieldID(clazz, "handle", "J");
    jlong handle = env->GetLongField(thiz, handle_fieldID);
    if (handle == 0) {
        return LOCK_FAIL;
    }
    Lock *lock = (Lock *) handle;
    return lock->open(port & 0xFF);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_cabinet_lock_lib_LockControl_startInspect(JNIEnv *env, jobject thiz) {
    jclass clazz = env->GetObjectClass(thiz);
    jfieldID handle_fieldID = env->GetFieldID(clazz, "handle", "J");
    jlong handle = env->GetLongField(thiz, handle_fieldID);
    if (handle == 0) {
        return LOCK_FAIL;
    }
    Lock *lock = (Lock *) handle;
    return lock->start_inspect();
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_cabinet_lock_lib_LockControl_stopInspect(JNIEnv *env, jobject thiz) {
    jclass clazz = env->GetObjectClass(thiz);
    jfieldID handle_fieldID = env->GetFieldID(clazz, "handle", "J");
    jlong handle = env->GetLongField(thiz, handle_fieldID);
    if (handle == 0) {
        return LOCK_FAIL;
    }
    Lock *lock = (Lock *) handle;
    return lock->stop_inspect();
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_example_cabinet_lock_lib_LockControl_getStatus(JNIEnv *env, jobject thiz,
                                                        jbyteArray status) {
    jclass clazz = env->GetObjectClass(thiz);
    jfieldID handle_fieldID = env->GetFieldID(clazz, "handle", "J");
    jlong handle = env->GetLongField(thiz, handle_fieldID);
    if (handle == 0) {
        return LOCK_FAIL;
    }
    Lock *lock = (Lock *) handle;
    unsigned char opened[60] = {0};
    int len = 60;
    lock->get_opened(opened, len);
    env->SetByteArrayRegion(status, 0, len, (jbyte *) opened);
    return LOCK_OK;
}

extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    JNIEnv *env;
    if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }
    jvm = vm;
    return JNI_VERSION_1_6;
}
